package com.example.everying.config;


import com.example.everying.constant.CacheConstants;
import com.example.everying.framework.websocket.handler.RedisMessageReceiver;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.util.Arrays;

@Configuration
@Slf4j
public class RedisConfig {
    private ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new  JavaTimeModule()); // 支持Java8时间类型
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);  // 禁用时间戳格式
        mapper.configure(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS,  false);
        return mapper;
    }
    // 消息监听容器
    @Bean
    public RedisMessageListenerContainer redisContainer(
            RedisConnectionFactory factory,
            MessageListenerAdapter listenerAdapter) {

        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        // 显式打印注册信息
        ChannelTopic topic = new ChannelTopic(CacheConstants.NOTIFICATION_KEY);
        log.info(" 注册监听器到频道: {} (字节: {})",
                topic.getTopic(),
                Arrays.toString(topic.getTopic().getBytes()));
        container.setConnectionFactory(factory);
        container.addMessageListener(listenerAdapter,  new ChannelTopic(CacheConstants.NOTIFICATION_KEY));
        container.addMessageListener(listenerAdapter,  new ChannelTopic(CacheConstants.OFFICIAL_NOTIFICATION_KEY));
        container.addMessageListener(listenerAdapter,  new ChannelTopic(CacheConstants.NOTICE_UNREAD_STATUS_KEY));
        container.setErrorHandler(e  -> log.error("Redis 监听异常", e));
        return container;
    }

    // 消息适配器（使用相同的序列化配置）
    @Bean
    public MessageListenerAdapter messageListenerAdapter(RedisMessageReceiver receiver) {
        MessageListenerAdapter adapter = new MessageListenerAdapter(receiver);
        adapter.setSerializer(new GenericJackson2JsonRedisSerializer(objectMapper()));
        return adapter;
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);

        // 使用Jackson序列化
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JavaTimeModule());
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.activateDefaultTyping(
                mapper.getPolymorphicTypeValidator(),
                ObjectMapper.DefaultTyping.NON_FINAL,
                JsonTypeInfo.As.PROPERTY
        );
        serializer.setObjectMapper(mapper);

        // 设置序列化器
        StringRedisSerializer stringSerializer = new StringRedisSerializer();
        template.setKeySerializer(stringSerializer);
        template.setHashKeySerializer(stringSerializer);
        template.setValueSerializer(serializer);
        template.setHashValueSerializer(serializer);

        template.afterPropertiesSet();
        return template;
    }
}
